#pragma once
#include <iostream>
#include <cmath>
#include <algorithm>
#include <type_traits>
#include <limits>

#define SUPOORT_C17 0

std::string getFileMd5(std::string filePath);
int32_t SignUtils_GetFileMD5(const char *pvFilePath, uint8_t *pvMD5Out);
int StrUtils_BytesToHexStr(uint8_t input_Bytes[], uint32_t BytesLen, char *output_HexStr, uint32_t out_len);

uint64_t getTime();
double getDoubleTime();
void getReqID(std::string &reqId);

std::string RandStr(const int len);

std::string encodeFromArray(const uint8_t *data, size_t len);

uint8_t BCC(const uint8_t *data, size_t dataLength);

#if SUPOORT_C17
template <typename T>
inline bool CompareValueIsZero(T value)
{
    if constexpr (std::is_same<T, float>::value)
    {
        float epsilon = std::numeric_limits<float>::epsilon() * 100;
        return std::abs(value) < espilon;
    }
    else if constexpr (std::is_same<T, double>::value)
    {
        double epsilon = std::numeric_limits<double>::epsilon() * 100;
        return std::abs(value) < espilon;
    }
    else
    {
        return (value == 0);
    }
}

template <typename T>
inline bool CompareValueIsSame(T value1, T value2)
{
    if constexpr (std::is_same<T, float>::value)
    {
        float epsilon = std::numeric_limits<float>::epsilon() * 100;
        return (value1 - value2) < espilon;
    }
    else if constexpr (std::is_same<T, double>::value)
    {
        double epsilon = std::numeric_limits<double>::epsilon() * 100;
        return (value1 - value2) < espilon;
    }
    else
    {
        return (value1 == value2);
    }
}
#else

// 通用类型的定义
template <typename T>
inline bool CompareValueIsZero(T value)
{
    return (value == 0);
}

// float 类型特化定义
template <>
inline bool CompareValueIsZero(float value)
{
    float epsilon = std::numeric_limits<float>::epsilon() * 100;
    return std::fabs(value) < epsilon;
}

// double 类型特化定义
template <>
inline bool CompareValueIsZero(double value)
{
    double epsilon = std::numeric_limits<double>::epsilon() * 100;
    return std::fabs(value) < epsilon;
}

enum CompareRes
{
    CMP_LOWER = -1,
    CMP_EQUAL = 0,
    CMP_GREATOR = 1,
};

// 通用类型的定义 (小于:-1 相等:0 大于:1)
template <typename T>
inline CompareRes CompareValue(T value1, T value2)
{
    if (value1 == value2)
    {
        return CMP_EQUAL;
    }
    else if (value1 > value2)
    {
        return CMP_GREATOR;
    }
    else
    {
        return CMP_LOWER;
    }
}

// float 类型特化定义 (小于:-1 相等:0 大于:1)
template <>
inline CompareRes CompareValue(float value1, float value2)
{
    float epsilon = std::numeric_limits<float>::epsilon() * 100;
    if (std::fabs(value1 - value2) < epsilon)
    {
        return CMP_EQUAL;
    }
    else if (value1 > value2)
    {
        return CMP_GREATOR;
    }
    else 
    {
        return CMP_LOWER;
    }
}

// double 类型特化定义 (小于:-1 相等:0 大于:1)
template <>
inline CompareRes CompareValue(double value1, double value2)
{
    double epsilon = std::numeric_limits<double>::epsilon() * 100;
    if (std::fabs(value1 - value2) < epsilon)
    {
        return CMP_EQUAL;
    }
    else if (value1 > value2)
    {
        return CMP_GREATOR;
    }
    else 
    {
        return CMP_LOWER;
    }
}

#endif
